package cn.itcast.mq.config;

import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.*;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.amqp.support.converter.MessageConverter;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
@Slf4j
public class CommonConfig implements ApplicationContextAware {

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        // 从IOC容器中 拿到 rabbitTemplate
        RabbitTemplate rabbitTemplate = applicationContext.getBean(RabbitTemplate.class);
       /* //设置发送者确认回调
        rabbitTemplate.setConfirmCallback(new RabbitTemplate.ConfirmCallback() {
            *//**
         *
         * @param correlationData  自定义的数据
         * @param ack  是否确认 true 代表消息已经达到exchange  fales  代表消息未达到exchange
         * @param cause  原因
         *//*
            @Override
            public void confirm(CorrelationData correlationData, boolean ack, String cause) {
                if (ack) {
                    log.info("消息发送成功...消息id : {}", correlationData.getId());
                } else {
                    log.error("消息发送失败...消息id : {}  原因id : {}", correlationData.getId(), cause);
                }
            }
        });*/
        // 设置发送者回执回调
        rabbitTemplate.setReturnCallback(new RabbitTemplate.ReturnCallback() {
            /**
             *
             * @param message 返回的消息对象
             * @param replyCode  回复编码
             * @param replyText  回复内容
             * @param exchange  交换机
             * @param routingKey   路由
             */
            @Override
            public void returnedMessage(Message message, int replyCode, String replyText, String exchange, String routingKey) {
                Integer receivedDelay = message.getMessageProperties().getReceivedDelay();
                if (receivedDelay > 0) {
                    log.info("接受到延迟返回 的消息");
                } else {
                    log.error("收到消息返还通知:  消息内容:{} 回复内容:{}  交换机:{}  路由key:{}", message, replyCode, replyText, exchange, routingKey);
                }
            }
        });

    }


    @Bean
    public Queue simpleQueue() {
        // 非持久化
        //  return new Queue("simple.queue", true);
        return QueueBuilder.durable("simple.queue").deadLetterExchange("dl.direct")
                .deadLetterRoutingKey("dl").build();
    }

    @Bean
    public DirectExchange directExchange() {
        // 非持久化
        return new DirectExchange("simple.direct", true, false);
    }


    @Bean
    public Binding binding() {
        Binding simple = BindingBuilder.bind(simpleQueue()).to(directExchange()).with("simple");
        return simple;
    }

    @Bean //交换机
    public DirectExchange dlExchange() {
        return new DirectExchange("dl.direct", true, false);
    }

    // 声明存储死信的队列 dl.queue
    @Bean   // 队列
    public Queue dlQueue() {
        return new Queue("dl.queue", true);
    }

    // 将死信队列 与 死信交换机绑定
    @Bean  // 路由
    public Binding dlBinding() {
        Binding simple = BindingBuilder.bind(dlQueue()).to(dlExchange()).with("dl");
        return simple;
    }

    @Bean //交换机
    public DirectExchange ttlExchange() {
        return new DirectExchange("ttl.direct", true, false);
    }

    // 声明存储死信的队列 dl.queue
    @Bean   // 队列
    public Queue ttlQueue() {
        // return new Queue("ttl.queue", true);
        return QueueBuilder.durable("ttl.queue").deadLetterExchange("dl.direct")
                .deadLetterRoutingKey("dl").ttl(10000).build();
    }

    @Bean  // 路由
    public Binding ttlBinding() {
        Binding simple = BindingBuilder.bind(ttlQueue()).to(ttlExchange()).with("ttl");
        return simple;
    }

    @Bean // 普通队列
    public Queue normalQueue() {
        return new Queue("normal.queue", true);
    }

    @Bean // 惰性队列
    public Queue lazyQueue() {
        return QueueBuilder.durable("lazy.queue").lazy().build();
    }
}

